
#include <BMesh>
#include "member_BConvexHull.h"

using namespace BWE;

member_BConvexHull::member_BConvexHull(BConvexHull* convexHull)
{
	boss = convexHull;
}
member_BConvexHull::~member_BConvexHull()
{

}

void member_BConvexHull::rebuild()
{
	const int size = planes.size();
	vertices.clear();
	faces.resize(size);
	for (int i = 0; i < size; ++i)
	{
		faces[i].reset();
	}
	for (int i = 0; i < size; ++i)
	{
		for (int j = i + 1; j < size; ++j)
		{
			for (int k = j + 1; k < size; ++k)
			{
				BVector point;
				if (intersectPlanes(planes[i], planes[j], planes[k], point))
				{
					int index = -1;
					for (int i = 0; i < vertices.size(); i++)
					{
						const BVector& v = vertices[i];
						if ((point - v).length2() < REAL_EPSILON)
						{
							index = i;
							break;
						}
					}
					if (index < 0)
					{
						index = vertices.size();
						vertices.append(point);
					}
					faces[i].append(index);
					faces[j].append(index);
					faces[k].append(index);
				}
			}
		}
	}
}
bool member_BConvexHull::intersectPlanes(const BPlane& p1, const BPlane& p2, const BPlane& p3, BVector& out) const
{
	const BVector& n1 = p1.normal();
	const BVector& n2 = p2.normal();
	const BVector& n3 = p3.normal();

	BReal det = n1.x() * (n2.y() * n3.z() - n3.y() * n2.z())
		- n1.y() * (n2.x() * n3.z() - n3.x() * n2.z())
		+ n1.z() * (n2.x() * n3.y() - n3.x() * n2.y());

	if (fabs(det) < REAL_EPSILON)
		return false;

	BReal invDet = 1.0 / det;

	out.x() = (-p1.dist() * (n2.y() * n3.z() - n3.y() * n2.z())
		+ p2.dist() * (n1.y() * n3.z() - n3.y() * n1.z())
		- p3.dist() * (n1.y() * n2.z() - n2.y() * n1.z())) * invDet;

	out.y() = (-n1.x() * (p2.dist() * n3.z() - p3.dist() * n2.z())
		+ n2.x() * (p1.dist() * n3.z() - p3.dist() * n1.z())
		- n3.x() * (p1.dist() * n2.z() - p2.dist() * n1.z())) * invDet;

	out.z() = (-n1.x() * (n2.y() * p3.dist() - n3.y() * p2.dist())
		+ n2.x() * (n1.y() * p3.dist() - n3.y() * p1.dist())
		- n3.x() * (n1.y() * p2.dist() - n2.y() * p1.dist())) * invDet;

	return true;
}
bool member_BConvexHull::intersectsSegment(const BLine& line) const
{
	BReal tEnter = 0.0;
	BReal tLeave = 1.0;
	for (int i = 0; i < planes.size(); i++)
	{
		const BPlane& plane = planes[i];
		BReal Adot = plane.distance(line.begin());
		BReal Bdot = plane.distance(line.end());

		if (Adot > REAL_EPSILON && Bdot > REAL_EPSILON)
			return false;
		if (Adot <= REAL_EPSILON && Bdot <= REAL_EPSILON)
			continue;

		BReal t = Adot / (Adot - Bdot);
		if (Adot > REAL_EPSILON)
		{
			tEnter = bMax(tEnter, t);
		}
		else
		{
			tLeave = bMin(tLeave, t);
		}

		if (tEnter > tLeave + REAL_EPSILON)
			return false;
	}
	return tEnter <= tLeave + REAL_EPSILON;
}

